export interface CompletionTestCase {
	original: string // Text with |cur| and |till| markers
	completion: string // Text to insert/overwrite
	appliedCompletion?: string | null
	cursorMarker?: string
	tillMarker?: string
}

interface ProcessedTestCase {
	input: {
		lastLineOfCompletionText: string
		currentText: string
		cursorPosition: number
	}
	expectedResult: {
		completionText: string
		range?: {
			start: number
			end: number
		}
	}
}

/**
 * Transforms human-readable test case into input and expected results.
 *
 * - `original`: Your original text with |cur| marking where the cursor is before completion,
 *      and |till| marking where the cursor should be after accepting completion (and this is
 *      the end of the actual applied completion)
 * - `completion`: LLM completion output
 * - `appliedCompletion` (optional):  part of the LLM completion output that is actually applied
 *      (written between |cur| and |till| in the original)
 *
 * For example, you have this line:
 *
 *     console.log("<cursor here>");
 *
 * and expect it to be completed this way:
 *
 *     console.log("foo: ", bar<cursor here>);
 *
 * with your completion coming from LLM being: `'foo: ", bar<cursor here>);'`
 *
 * Your input to this function should be:
 * - original: `'console.log("|cur|"|till|);'`
 * - completion: `'foo: ", bar);'`
 * - appliedCompletion: `'foo: ", bar'`
 *
 * Output: input and expected output of {@link core/autocomplete/util/processSingleLineCompletion/processSingleLineCompletion|processSingleLineCompletion()}
 *
 */
export function processTestCase({
	original,
	completion,
	appliedCompletion = null,
	cursorMarker = "|cur|",
	tillMarker = "|till|",
}: CompletionTestCase): ProcessedTestCase {
	// Validate cursor marker
	if (!original.includes(cursorMarker)) {
		throw new Error("Cursor marker not found in original text")
	}

	const cursorPos = original.indexOf(cursorMarker)
	original = original.replace(cursorMarker, "")

	let tillPos = original.indexOf(tillMarker)
	if (tillPos < 0) {
		tillPos = cursorPos
	} else {
		original = original.replace(tillMarker, "")
	}

	// Calculate currentText based on what's between cursor and till marker
	const currentText = original.substring(cursorPos)

	return {
		input: {
			lastLineOfCompletionText: completion,
			currentText,
			cursorPosition: cursorPos,
		},
		expectedResult: {
			completionText: appliedCompletion || completion,
			range:
				cursorPos === tillPos
					? undefined
					: {
							start: cursorPos,
							end: tillPos,
						},
		},
	}
}
